﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "comboxClickable.h"
#include "ui_setTime.h"
#include "ui_about.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setWindowTitle("定日镜控制系统 ModBus v" g_SoftwareVersion);


    /* 初始化窗口 */
    ui->stackedWidget->setCurrentIndex(1);
    ui->funcView->setCurrentIndex(0);

    /* 实例化就地控制器信息 */
    m_info = new localInfo_s;
    memset(m_info, 0, sizeof(localInfo_s));

    /* 切换功能页面 */
    m_funPageBtn[0] = ui->btnInfo;
    m_funPageBtn[1] = ui->btnDevSet;
    m_funPageBtn[2] = ui->btnDnaSet;
    m_funPageBtn[3] = ui->btnCmdSet;
    m_funPageBtn[4] = ui->btnMotorSet;
    for (int i = 0; i < FUN_PAGE_NUM; i++)
    {
        connect(m_funPageBtn[i], &QPushButton::clicked, [=](){
            ui->funcView->setCurrentIndex(i);
        });
    }

    /* HMI状态 */
    // 占线、非占线
    m_hmiBusyBtn[0] = ui->hmiBusyOff;
    m_hmiBusyBtn[1] = ui->hmiBusyOn;
    for (quint16 i = 0; i < 2; i++)
    {
        connect(m_hmiBusyBtn[i], &QPushButton::clicked, this, [=](){
            modbusRegContral(0xce, i);
        });
    }

    // 在线、离线
    m_hmiOnlineBtn[0] = ui->hmiOffline;
    m_hmiOnlineBtn[1] = ui->hmiOnline;
    for (quint16 i = 0; i < 2; i++)
    {
        connect(m_hmiOnlineBtn[i], &QPushButton::clicked, this, [=](){
            modbusRegContral(0xd0, i);
        });
    }

    // 模式切换
    m_hmiModeBtn[0] = ui->modeSfcsAps;
    m_hmiModeBtn[1] = ui->modeSfcsCal;
    m_hmiModeBtn[2] = ui->modeSfcsClean;
    m_hmiModeBtn[3] = ui->modeSfcs;
    m_hmiModeBtn[4] = ui->modeLoc;
    for (quint16 i = 0; i < 5; i++)
    {
        connect(m_hmiModeBtn[i], &QPushButton::clicked, this, [=](){
            modbusRegContral(0xcf, i + 1, MODBUS_REG_FEEDBACK);
        });
    }


    /* 定时器 */
    ui->refrTime->setText("等待设备连接...");
    m_timer1s = new QTimer(this);
    m_timer1s->setInterval(1000);
    connect(m_timer1s, &QTimer::timeout, this, [=](){
        systemReg_s *s = &m_info->system;
        QString t = QString(s->timestamp);
        QDateTime time = QDateTime::fromString(t, "yyyy-M-d h:m:s");
        sprintf(s->timestamp, "%s", time.addSecs(1).toString("yyyy-MM-dd hh:mm:ss").toUtf8().data());
        ui->systime->setText(s->timestamp);
    });


    /* 串口 */
//    m_modbusThread = new QThread;
    m_modbus = new Modbus(this);

    // 查询可用串口
    connect(this, &MainWindow::searchSerialPortrt, m_modbus, &Modbus::searchAvailablePorts);
    // 刷新串口号下拉框
    connect(m_modbus, &Modbus::refrAvailablePorts, this, &MainWindow::refrSerialPort);
    // 点击串口下拉框时刷新可用串口
    connect(ui->serialPort, &ComboxClickable::clicked, this, [=](){
        QString curPort = ui->serialPort->currentText();
        emit searchSerialPortrt();
        ui->serialPort->setCurrentText(curPort);
    });
    // 设置串口参数
    connect(this, &MainWindow::setMosbusParam, m_modbus, &Modbus::setModbusParam);
    // 设置串口状态
    connect(this, &MainWindow::setModbusEnable, m_modbus, &Modbus::setModbusEnable);
    // 接收串口数据
    connect(m_modbus, &Modbus::dataReady, this, &MainWindow::modbusDataReady);
    // 写入寄存器
    connect(this, &MainWindow::modbusSetRegs, m_modbus, &Modbus::modbusSetRegs);
    // 写入寄存器状态反馈
    connect(m_modbus, &Modbus::modbusWriteFeedback, this, &MainWindow::modbusWriteFeedback);
    // 串口未启用提示
    connect(m_modbus, &Modbus::isUnenable, this, [=](){
        QMessageBox::warning(this, "错误", "请先打开串口");
    });
    // 刷新设备参数
    connect(ui->refrInfoBtn, &QToolButton::clicked, m_modbus, &Modbus::refrInfo);
    // modbus断连
    connect(m_modbus, &Modbus::disconnect, this, [=](){
//        if (m_timer1s) m_timer1s->stop();
//        if (m_info) memset(m_info, 0, sizeof(localInfo_s));
        ui->refrTime->setText("等待设备连接...");
    });

    // 启动串口线程
//    m_modbus->moveToThread(m_modbusThread);
//    m_modbusThread->start();
    emit searchSerialPortrt();

    // 串口设置
    connect(ui->serialSetBtn, &QPushButton::clicked, this, [=](){
        QStringList portList;
        for (int i = 0; i < ui->serialPort->count(); i++)
        {
            portList.append(ui->serialPort->itemText(i));
        }

        Ui_SerialSet * serialSet =
                new Ui_SerialSet(portList, ui->serialPort->currentIndex(), ui->serialBaud->currentIndex(), this);

        connect(serialSet, &Ui_SerialSet::setSerialInfo, this, [=](ModbusRtuParam_t info){
            ui->serialPort->setCurrentText(info.port);
            ui->serialBaud->setCurrentText(QString::number(info.baud));
            emit setMosbusParam(info);
        });

        serialSet->show();
    });

    // 串口启用开关
    connect(ui->serialOpenBtn, &QPushButton::clicked, [=](){
        if (ui->serialOpenBtn->isChecked())
        {
            ui->serialOpenBtn->setText("关闭串口");
            ui->serialPort->setEnabled(false);
            ui->serialBaud->setEnabled(false);
            ui->serialSetBtn->setEnabled(false);
            m_timer1s->start();
        }

        else
        {
            ui->serialOpenBtn->setText("打开串口");
            ui->serialPort->setEnabled(true);
            ui->serialBaud->setEnabled(true);
            ui->serialSetBtn->setEnabled(true);
            ui->refrTime->setText("等待设备连接...");
        }

        emit setModbusEnable(ui->serialOpenBtn->isChecked(),
                             ui->serialPort->currentText(),
                             ui->serialBaud->currentText());
    });

    /* 关于 */
    connect(ui->actionAbout, &QAction::triggered, this, [=](){
        UiAbout * setTime = new UiAbout();
        setTime->show();
    });
}

MainWindow::~MainWindow()
{
    delete ui;
    delete m_info;
    m_timer1s->stop();
    m_timer1s->deleteLater();
    m_timer1s = nullptr;
    m_modbus->deleteLater();
    m_modbus = nullptr;
}

void MainWindow::modbusWriteFeedback(ModbusRegCmd_e type, bool ret)
{
    if (!ret)
    {
        QMessageBox::warning(this, "设置失败", "设备响应超时...");
        return;
    }

    switch (type) {
    case MODBUS_REG_SET_SYSTEM_TIME:
        QMessageBox::information(this, "设置成功", "设备系统时间设置成功");
        break;
    case MODBUS_REG_SET_DEV_REBOOT:
        QMessageBox::information(this, "设置成功", "设备正在重启...");
        break;
    case MODBUS_REG_SET_DEV_RESET:
        QMessageBox::information(this, "设置成功", "设备已重置");
        break;

    case MODBUS_REG_NO_FEEDBACK:
        break;

    default:
        QMessageBox::information(this, "设置成功", "设置成功");
        break;
    }

}

void MainWindow::refrSerialPort(QStringList portList)
{
    ui->serialPort->clear();
    for (int i = 0; i < portList.size(); i++)
    {
        ui->serialPort->addItem(portList.at(i));
    }
}

void MainWindow::modbusDataReady(ModbusRegCmd_e type, QModbusDataUnit data)
{
//    qDebug() << "读到数据为：" << data.values();

    if (data.values().size() == 0)
    {
        qDebug() << QString("接收数据的长度错误");
        return;
    }

    switch (type) {
    case MODBUS_REG_GET_SYSTEM:
        qInfo() << "Modbus_Reg_Get_System";
        modbusGetSystemHandle(data.values());
        break;
    case MODBUS_REG_GET_MOTOR_CTRL_M:
        qInfo() << "Modbus_Reg_Get_Motor_Ctrl_m";
        modbusGetMotorCtrlHandle(data.values(), 0);
        break;
    case MODBUS_REG_GET_MOTOR_CTRL_S:
        qInfo() << "Modbus_Reg_Get_Motor_Ctrl_s";
        modbusGetMotorCtrlHandle(data.values(), 1);
        break;
    case MODBUS_REG_GET_APP:
        qInfo() << "Modbus_Reg_Get_App";
        modbusGetAppHandle(data.values());
        break;
    case MODBUS_REG_GET_MOTOR_DATA:
//        qInfo() << "Modbus_Reg_Get_Motor_Data";
        modbusGetMotorDataHandle(data.values());
        break;
    case MODBUS_REG_GET_ALOG_DATA:
//        qInfo() << "Modbus_Reg_get_Alog_Data";
        modbusGetAlogDataHandle(data.values());
        break;
    case MODBUS_REG_GET_SYSTEM_TIME:
        qInfo() << "↑↑↑获取系统时间↑↑↑";
        modbusGetSystemTimeHandle(data.values());
        break;
    case MODBUS_REG_GET_CMD:
        qInfo() << "↑↑↑获取CMD数据↑↑↑";
        modbusGetCmdHandle(data.values());
        break;
    case MODBUS_REG_GET_DNA:
        qInfo() << "↑↑↑获取DNA数据↑↑↑";
        modbusGetDnaHandle(data.values());
        break;


    default:
        qWarning() << "Modbus Read Unknow Type !";
        break;
    }
}

void MainWindow::modbusGetSystemHandle(QVector<quint16> data)
{
    systemReg_s *s = &m_info->system;

    // 解析数据
    s->maddr     = data[0];
    s->baud      = data[1];
    s->logLevel  = data[2];
    s->regReboot = data[3];
    s->regReset  = data[4];

    sprintf(s->timestamp, "%u-%u-%u %u:%u:%u", data[5], data[6], data[7], data[8], data[9], data[10]);

    s->uid = (((qint64)data[11] << 48) | ((qint64)data[12] << 32) | ((qint64)data[13] << 16 | (qint64)data[14]));

    sprintf(s->hVer, "%u.%u.%u", data[15], data[16], data[17]);
    sprintf(s->sVer, "%u.%u.%u", data[18], data[19], data[20]);

    sprintf(s->swbTiem, "20%u-%02u-%02u %u:%u:%u",
            data[21] >> 8, data[21] & 0xff,
            data[22] >> 8, data[22] & 0xff,
            data[23] >> 8, data[23] & 0xff);

    sprintf(s->bootVer, "%u.%u.%u", data[24], data[25], data[26]);

    // 刷新ui
    ui->title_addr->setText(QString("0x%1").arg(s->maddr, 2, 16, QLatin1Char('0')));
    ui->l_maddr->setText(QString("0x%1").arg(s->maddr, 2, 16, QLatin1Char('0')));

    ui->l_baudrate->setText(g_baudrate[s->baud]);
    ui->l_loglevel->setText(g_logLevel[s->logLevel]);
    ui->systime->setText(QString(s->timestamp));

    ui->l_uid->setText(QString::number(s->uid));
    ui->title_uid->setText(QString::number(s->uid));

    ui->l_swver->setText(s->sVer);
    ui->l_hwver->setText(s->hVer);
    ui->l_swbtime->setText(s->swbTiem);

    ui->devMaddr->setText(QString::number(s->maddr, 16));
    ui->devLogLevel->setCurrentIndex(s->logLevel);
    ui->devBaudrate->setCurrentIndex(s->baud);

    ui->l_bootLoaderVer->setText(s->bootVer);
}

void MainWindow::modbusGetMotorCtrlHandle(QVector<quint16> data, int motor)
{
    motorCtrlReg_s *m = &m_info->motorCtrl[motor];

    quint16 buf[128] = {0};
    for (int i = 0; i < data.size(); i++)
    {
        buf[i] = data.at(i);
    }

    // 解析数据
    memcpy(m, buf, sizeof(motorCtrlReg_s));
}

void MainWindow::modbusGetAppHandle(QVector<quint16> data)
{
    int idx = 0;
    appReg_s * a = &m_info->app;
    memset(a, 0, sizeof(appReg_s));

    // 解析数据
    a->clusterDbg = data[idx++];
    a->motorDbg   = data[idx++];
    a->motorLog_m = data[idx++];
    a->motorLog_s = data[idx++];
    a->stop       = data[idx++];
    unpackVersion(data.mid(idx, 2), a->sVer_m); idx += 2;
    sprintf(a->hVer_m, "%c.%c.%c", data[idx] >> 8, (quint8)data[idx], (quint8)data[idx + 1]); idx += 2;
    unpackVersion(data.mid(idx, 2), a->sVer_s); idx += 2;
    sprintf(a->hVer_s, "%c.%c.%c", data[idx] >> 8, (quint8)data[idx], (quint8)data[idx + 1]); idx += 2;
    a->saveNVM = data[idx++];

    a->busy      = data[idx++];
    a->mode      = data[idx++];
    a->state     = data[idx++];
    a->auto_switch_enable   = data[idx++];
    a->errReset  = data[idx++];
    a->warnClean = data[idx++];
    a->emgStop   = data[idx++];
    a->engineer_authority   = data[idx++];
    a->simulate_reflected_to_safety_zone     = data[idx++];
    a->in_calibration_queue = data[idx++];
    a->disable_backup_point_corrdinate_limit = data[idx++];
    a->simulate_zero_point_correction_ready  = data[idx++];
    a->simulate_check_limit_pos_ready = data[idx++];
    a->simulate_back_horizontal_ready = data[idx++];
    a->simulate_emergency_placement   = data[idx++];
    a->code_multiplier_val_enable     = data[idx++];

    uint16ToDoubleByte(a->codeVal, &data[idx]); idx += 2;

    a->enable_incident_light_dead_zone = data[idx++];
    a->disable_backup_point_distance_requirements = data[idx++];
    a->enable_advance_travel     = data[idx++];
    a->angle_travel_advance_1min = data[idx++];
    a->enable_gravity_compensation     = data[idx++];
    a->enable_correction_compensation  = data[idx++];
    a->powerEnable = data[idx++];

    a->powMax_m = data[idx++];
    a->powMax_s = data[idx++];

    // 刷新ui
    if (a->busy <= 1)
        m_hmiBusyBtn[a->busy]->setChecked(true);
    if (a->state <= 1)
        m_hmiOnlineBtn[a->state]->setChecked(true);
    if (a->mode >= 1 && a->mode <= 5)
        m_hmiModeBtn[a->mode - 1]->setChecked(true);

    ui->locEmerStopBtn->setChecked(a->emgStop);
    ui->auto_switch_enable->setChecked(a->auto_switch_enable);
    ui->engineer_authority->setChecked(a->engineer_authority);
    ui->simulate_reflected_to_safety_zone->setChecked(a->simulate_reflected_to_safety_zone);
    ui->in_calibration_queue->setChecked(a->in_calibration_queue);
    ui->disable_backup_point_corrdinate_limit->setChecked(a->disable_backup_point_corrdinate_limit);
    ui->simulate_zero_point_correction_ready->setChecked(a->simulate_zero_point_correction_ready);
    ui->simulate_check_limit_pos_ready->setChecked(a->simulate_check_limit_pos_ready);
    ui->simulate_back_horizontal_ready->setChecked(a->simulate_back_horizontal_ready);
    ui->simulate_emergency_placement->setChecked(a->simulate_emergency_placement);
    ui->code_multiplier_val_enable->setChecked(a->code_multiplier_val_enable);
    ui->code_multiplier_val_enable->setChecked(a->code_multiplier_val_enable);

    ui->code_multiplier_val->setText(QString::number(a->codeVal));;
    ui->maxPowerMain->setText(QString::number(a->powMax_m));
    ui->maxPowerSub->setText(QString::number(a->powMax_s));

    ui->l_clusterDbg->setText(a->clusterDbg == 0 ? "关闭" : "打开");
    ui->l_motorDbg->setText(a->motorDbg == 0 ? "关闭" : "打开");
    ui->devClusterDbg->setChecked(a->clusterDbg);
    ui->devMotorDbg->setChecked(a->motorDbg);

    ui->motorSetLog1->setCurrentIndex(a->motorLog_m);
    ui->motorSetLog2->setCurrentIndex(a->motorLog_s);

    ui->locEmerStopBtn->setChecked(a->emgStop);
    ui->enablePowerManger->setChecked(a->powerEnable);

    ui->auto_switch_enable->setChecked(a->auto_switch_enable);
    ui->engineer_authority->setChecked(a->engineer_authority);
    ui->simulate_reflected_to_safety_zone->setChecked(a->simulate_reflected_to_safety_zone);
    ui->in_calibration_queue->setChecked(a->in_calibration_queue);
    ui->disable_backup_point_corrdinate_limit->setChecked(a->disable_backup_point_corrdinate_limit);
    ui->simulate_zero_point_correction_ready->setChecked(a->simulate_zero_point_correction_ready);
    ui->simulate_check_limit_pos_ready->setChecked(a->simulate_check_limit_pos_ready);
    ui->simulate_back_horizontal_ready->setChecked(a->simulate_back_horizontal_ready);
    ui->simulate_emergency_placement->setChecked(a->simulate_emergency_placement);
    ui->code_multiplier_val_enable->setChecked(a->code_multiplier_val_enable);
    ui->enable_incident_light_dead_zone->setChecked(a->enable_incident_light_dead_zone);
    ui->disable_backup_point_distance_requirements->setChecked(a->disable_backup_point_distance_requirements);
    ui->enable_advance_travel->setChecked(a->enable_advance_travel);
    ui->angle_travel_advance_1min->setChecked(a->angle_travel_advance_1min);
    ui->enable_gravity_compensation->setChecked(a->enable_gravity_compensation);
    ui->enable_correction_compensation->setChecked(a->enable_correction_compensation);

    ui->motorSwVer_1->setText(a->sVer_m);
    ui->motorHwVer_1->setText(a->hVer_m);
    ui->motorSwVer_2->setText(a->sVer_s);
    ui->motorHwVer_2->setText(a->hVer_s);

    if (a->stop) {
        ui->btnStop->setIcon(QIcon(":/res/reload-restore-icon-27.png"));
    } else {
        ui->btnStop->setIcon(QIcon(":/res/stop.png"));
    }
}

void MainWindow::modbusGetMotorDataHandle(QVector<quint16> data)
{
    int idx = 0;
    motorDataReg_s * m = nullptr;

    /* 主轴 */
    m = &m_info->motorData[0];
    memset(m, 0, sizeof(motorDataReg_s));
    // 解析数据
    uint16ToDoubleByte(m->curTrip,   &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curSpeed,  &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curEi,     &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curPower,  &data[idx]); idx += 2;
    m->curMode = data[idx++];
    m->state   = data[idx++];
    uint16ToDoubleByte(m->inputVal,  &data[idx]); idx += 2;
    m->errCode = data[idx++];
    uint16ToDoubleByte(m->switchPos, &data[idx]); idx += 2;

    m->flagAuto      = data[idx++];
    m->flagEnable    = data[idx++];
    m->flagFault     = data[idx++];
    m->flagRun       = data[idx++];
    m->flagFinish    = data[idx++];
    m->flagLimitUp   = data[idx++];
    m->flagLimitDown = data[idx++];

    uint16ToDoubleByte(m->voltage,  &data[idx]); idx += 2;
    uint16ToDoubleByte(m->hallCode, &data[idx]); idx += 2;
    uint16ToDoubleByte(m->code,     &data[idx]); idx += 2;
    uint16ToDoubleByte(m->voltage,  &data[idx]); idx += 2;

    // 刷新ui
    ui->trip_1->setText(QString::number(m->curTrip));
    ui->speed_1->setText(QString::number(m->curSpeed));
    ui->ei_1->setText(QString::number(m->curEi));
    ui->power_1->setText(QString::number(m->curPower));
    ui->workMode_1->setText(g_curMode.value(m->curMode, QString::number(m->curMode)));
    ui->state_1->setText(QString("0x%1").arg(m->state, 0, 16));
    ui->io_1->setText(QString("0x%1").arg(m->inputVal, 0, 16));
    ui->err_1->setText(QString("0x%1").arg(m->errCode, 0, 16));
    ui->limit_1->setText(QString::number(m->switchPos));

    ui->flagAuto_1->setStyleSheet(m->flagAuto ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagEnable_1->setStyleSheet(m->flagEnable ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagFault_1->setStyleSheet(m->flagFault ? MOTOR_FLAG_ERR_ON : MOTOR_FLAG_ERR_OFF);
    ui->flagRun_1->setStyleSheet(m->flagRun ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagFinish_1->setStyleSheet(m->flagFinish ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagLimitUp_1->setStyleSheet(m->flagLimitUp ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagLimitDown_1->setStyleSheet(m->flagLimitDown ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);

    ui->vol_1->setText(QString::number(m->voltage));
    ui->hall_1->setText(QString::number(m->hallCode));
    ui->pulses_1->setText(QString::number(m->code));
    ui->zero_1->setText(QString::number(m->voltage));

    /* 主轴 */
    m = &m_info->motorData[1];
    memset(m, 0, sizeof(motorDataReg_s));
    // 解析数据
    uint16ToDoubleByte(m->curTrip,   &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curSpeed,  &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curEi,     &data[idx]); idx += 2;
    uint16ToDoubleByte(m->curPower,  &data[idx]); idx += 2;
    m->curMode = data[idx++];
    m->state   = data[idx++];
    uint16ToDoubleByte(m->inputVal,  &data[idx]); idx += 2;
    m->errCode = data[idx++];
    uint16ToDoubleByte(m->switchPos, &data[idx]); idx += 2;

    m->flagAuto      = data[idx++];
    m->flagEnable    = data[idx++];
    m->flagFault     = data[idx++];
    m->flagRun       = data[idx++];
    m->flagFinish    = data[idx++];
    m->flagLimitUp   = data[idx++];
    m->flagLimitDown = data[idx++];

    uint16ToDoubleByte(m->voltage,  &data[idx]); idx += 2;
    uint16ToDoubleByte(m->hallCode, &data[idx]); idx += 2;
    uint16ToDoubleByte(m->code,     &data[idx]); idx += 2;
    uint16ToDoubleByte(m->voltage,  &data[idx]); idx += 2;
    // 刷新UI
    ui->trip_2    ->setText(QString::number(m->curTrip));
    ui->speed_2   ->setText(QString::number(m->curSpeed));
    ui->ei_2      ->setText(QString::number(m->curEi));
    ui->power_2   ->setText(QString::number(m->curPower));
    ui->workMode_2->setText(g_curMode.value(m->curMode, QString::number(m->curMode)));
    ui->state_2   ->setText(QString("0x%1").arg(m->state, 0, 16));
    ui->io_2      ->setText(QString("0x%1").arg(m->inputVal, 0, 16));
    ui->err_2     ->setText(QString("0x%1").arg(m->errCode, 0, 16));
    ui->limit_2   ->setText(QString::number(m->switchPos));

    ui->flagAuto_2     ->setStyleSheet(m->flagAuto      ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagEnable_2   ->setStyleSheet(m->flagEnable    ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagFault_2    ->setStyleSheet(m->flagFault     ? MOTOR_FLAG_ERR_ON : MOTOR_FLAG_ERR_OFF);
    ui->flagRun_2      ->setStyleSheet(m->flagRun       ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagFinish_2   ->setStyleSheet(m->flagFinish    ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagLimitUp_2  ->setStyleSheet(m->flagLimitUp   ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);
    ui->flagLimitDown_2->setStyleSheet(m->flagLimitDown ? MOTOR_FLAG_ON : MOTOR_FLAG_OFF);

    ui->vol_2   ->setText(QString::number(m->voltage));
    ui->hall_2  ->setText(QString::number(m->hallCode));
    ui->pulses_2->setText(QString::number(m->code));
    ui->zero_2  ->setText(QString::number(m->voltage));


    /* 更新时间 */
    ui->refrTime->setText(QString("更新时间：%1").arg(QDateTime::currentDateTime().toString("yyyy年MM月dd日 hh:mm:ss dddd").toUtf8().data()));
}

void MainWindow::modbusGetAlogDataHandle(QVector<quint16> data)
{
    int idx = 0;
    alogDataReg_s * a = &m_info->alogData;
    memset(a, 0, sizeof(alogDataReg_s));

    // 解析数据
    uint16ToDoubleByte(a->x, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->y, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->z, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->normalHeight,  &data[idx]); idx += 2;
    uint16ToDoubleByte(a->normalAzimuth, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->rotateMain,    &data[idx]); idx += 2;
    uint16ToDoubleByte(a->rotateSub,     &data[idx]); idx += 2;
    uint16ToDoubleByte(a->tripMain,      &data[idx]); idx += 2;
    uint16ToDoubleByte(a->tripSub,       &data[idx]); idx += 2;
    uint16ToDoubleByte(a->sunHeight,     &data[idx]); idx += 2;
    uint16ToDoubleByte(a->sunHor,        &data[idx]); idx += 2;

    a->execState   = data[idx++];
    a->finishState = data[idx++];
    uint16ToDoubleByte(a->errCode, &data[idx]); idx += 2;

    a->curMode     = data[idx++];
    a->curOrder    = data[idx++];
    a->curAttitude = data[idx++];
    a->preMode     = data[idx++];
    a->preOrder    = data[idx++];
    a->preAttitude = data[idx++];

    uint16ToDoubleByte(a->backRotateMain, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backRotateSub,  &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backAzimuth,    &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backHigh, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backX, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backY, &data[idx]); idx += 2;
    uint16ToDoubleByte(a->backZ, &data[idx]); idx += 2;

    // 刷新ui
    ui->motorX->setText(QString::number(a->x));
    ui->motorY->setText(QString::number(a->y));
    ui->motorZ->setText(QString::number(a->z));
    ui->normalHeight->setText(QString::number(a->normalHeight));
    ui->normalAzimuth->setText(QString::number(a->normalAzimuth));
    ui->mainRotation->setText(QString::number(a->rotateMain));
    ui->subRotation->setText(QString::number(a->rotateSub));
    ui->mainTravel->setText(QString::number(a->tripMain));
    ui->subTravel->setText(QString::number(a->tripSub));
    ui->sunHeight->setText(QString::number(a->sunHeight));
    ui->sunHorizontal->setText(QString::number(a->sunHor));

    ui->pbkRotationPr->setText(QString::number(a->backRotateMain));
    ui->pbkRotationSc->setText(QString::number(a->backRotateSub));
    ui->pbkAzimuth->setText(QString::number(a->backAzimuth));
    ui->pbkHigh->setText(QString::number(a->backHigh));
    ui->pbkBodyX->setText(QString::number(a->backX));
    ui->pbkBodyY->setText(QString::number(a->backY));
    ui->pbkBodyZ->setText(QString::number(a->backZ));

    ui->execState->setText(QString::number(a->execState));
    ui->finishState->setText(g_finishState[a->finishState]);
    ui->errCode->setText(QString::number(a->errCode));

    ui->curMode->setText(QString::number(a->curMode));
    ui->curModeDesc->setText(g_cmdMode.value(a->curMode, "未知模式"));
    ui->preMode->setText(QString::number(a->preMode));
    ui->preModeDesc->setText(g_cmdMode.value(a->preMode, "未知模式"));
    ui->curOrder->setText(QString::number(a->curOrder));
    ui->curOrderDesc->setText(g_cmdOrder.value(a->curOrder, "未知指令"));
    ui->preOrder->setText(QString::number(a->preOrder));
    ui->preOrderDesc->setText(g_cmdOrder.value(a->preOrder, "未知指令"));
    ui->curAttitude->setText(QString::number(a->curAttitude));
    ui->curAttitudeDesc->setText(g_cmdAttitude.value(a->curAttitude, "未知姿态"));
    ui->preAttitude->setText(QString::number(a->preAttitude));
    ui->preAttitudeDesc->setText(g_cmdAttitude.value(a->preAttitude, "未知姿态"));
}

void MainWindow::modbusGetSystemTimeHandle(QVector<quint16> data)
{
    sprintf(m_info->system.timestamp, "%u-%02u-%02u %02u:%02u:%02u", data[0], data[1], data[2], data[3], data[4], data[5]);
    QString timestamp = QString(m_info->system.timestamp);
    QMessageBox::information(this, "系统时间", QString("当前设备系统时间为：%1").arg(timestamp));
    ui->systime->setText(timestamp);
}

void MainWindow::modbusGetCmdHandle(QVector<quint16> data)
{
    int idx = 0;
    cmdReg_s * c = &m_info->cmd;
    memset(c, 0, sizeof(cmdReg_s));

    // 解析数据
    c->cmd = data[idx++];
    uint16ToDoubleByte(c->x, &data[idx]); idx += 2;
    uint16ToDoubleByte(c->y, &data[idx]); idx += 2;
    uint16ToDoubleByte(c->z, &data[idx]); idx += 2;

    // 刷新UI
    ui->cmdCmd->setCurrentIndex(c->cmd);
    ui->cmdX->setText(QString::number(c->x));
    ui->cmdY->setText(QString::number(c->y));
    ui->cmdZ->setText(QString::number(c->z));
}

void MainWindow::modbusGetDnaHandle(QVector<quint16> data)
{
    int idx = 0;
    dnaReg_s * d = &m_info->dna;
    memset(d, 0, sizeof(dnaReg_s));

    /* 数据处理 */
    d->fieldId  = data[idx++]; // 镜场标识id
    d->row      = data[idx++]; // 行
    d->col      = data[idx++]; // 列
    d->sector   = data[idx++]; // 区
    d->hcdi     = data[idx++]; // 组
    d->switchId = data[idx++]; // 段
    d->line     = data[idx++]; // 链
    d->lineId   = data[idx++]; // 号

    uint16ToDoubleByte(d->m01, &data[idx]); idx += 2; // 主推杆完全缩回时，主轴耳轴与主推杆末端的长度
    uint16ToDoubleByte(d->m02, &data[idx]); idx += 2; // 副推杆完全缩回时，副轴耳轴与副推杆末端的长度
    uint16ToDoubleByte(d->m03, &data[idx]); idx += 2; // 主推杆耳轴到主轴的水平距离
    uint16ToDoubleByte(d->m04, &data[idx]); idx += 2; // 主推杆耳轴到主轴的垂直距离
    uint16ToDoubleByte(d->m05, &data[idx]); idx += 2; // 主轴万向节点到主轴的水平距离
    uint16ToDoubleByte(d->m06, &data[idx]); idx += 2; // 主轴万向节点到主轴的垂直距离
    uint16ToDoubleByte(d->m07, &data[idx]); idx += 2; // 副推杆耳轴到副轴的水平距离
    uint16ToDoubleByte(d->m08, &data[idx]); idx += 2; // 副推杆耳轴到副轴的垂直距离
    uint16ToDoubleByte(d->m09, &data[idx]); idx += 2; // 副轴到副推杆末端的水平距离
    uint16ToDoubleByte(d->m10, &data[idx]); idx += 2; // 副轴到副推杆末端的垂直距离
    uint16ToDoubleByte(d->m11, &data[idx]); idx += 2; // 主轴相对于立柱端板的仰角
    uint16ToDoubleByte(d->m12, &data[idx]); idx += 2; // 主轴相对于立柱端板的方位角
    uint16ToDoubleByte(d->m13, &data[idx]); idx += 2; // 副轴与反射面的非正交角，即副轴与镜面的夹角
    uint16ToDoubleByte(d->m14, &data[idx]); idx += 2; // 主轴与副轴的非正交角，即主轴与副轴在水平面上的投影交角与90°之差
    uint16ToDoubleByte(d->m21, &data[idx]); idx += 2; // 立柱安装倾角矢量仰角
    uint16ToDoubleByte(d->m22, &data[idx]); idx += 2; // 立柱安装倾角矢量方位角
    uint16ToDoubleByte(d->m23, &data[idx]); idx += 2; // 法兰方位角旋转
    uint16ToDoubleByte(d->m24, &data[idx]); idx += 2; // 立柱镜场位置的x坐标
    uint16ToDoubleByte(d->m25, &data[idx]); idx += 2; // 立柱镜场位置的y坐标
    uint16ToDoubleByte(d->m26, &data[idx]); idx += 2; // 立柱镜场位置的z坐标

    uint16ToDoubleByte(d->longitude, &data[idx]); idx += 2; // 经度
    uint16ToDoubleByte(d->latitude , &data[idx]); idx += 2; // 纬度
    uint16ToDoubleByte(d->altitude , &data[idx]); idx += 2; // 海拔高度

    d->typePr = data[idx++];     // 主推杆类型
    d->typeSc = data[idx++];     // 副推杆类型
    uint16ToDoubleByte(d->weight,     &data[idx]); idx += 2; // 定日镜重量
    uint16ToDoubleByte(d->temprature, &data[idx]); idx += 2; // 组装时温度
    uint16ToDoubleByte(d->pitchPr,    &data[idx]); idx += 2; // 主轴推杆螺距
    uint16ToDoubleByte(d->pitchSc,    &data[idx]); idx += 2; // 副轴推杆螺距
    uint16ToDoubleByte(d->rationPr,   &data[idx]); idx += 2; // 主推杆减速比
    uint16ToDoubleByte(d->rationSc,   &data[idx]); idx += 2; // 副推杆减速比
    d->pulsesPr = data[idx++];   // 主轴电机极对数
    d->pulsesSc = data[idx++];   // 副轴电机极对数
    uint16ToDoubleByte(d->tripPr,     &data[idx]); idx += 2; // 回平姿态主轴推杆行程
    uint16ToDoubleByte(d->tripSc,     &data[idx]); idx += 2; // 回平姿态副轴推杆行程
    uint16ToDoubleByte(d->curvature,  &data[idx]); idx += 2; // 镜面曲率

    /* 刷新UI */
    ui->devFieleId ->setText(QString::number(d->fieldId));
    ui->devRow     ->setText(QString::number(d->row));
    ui->devCol     ->setText(QString::number(d->col));
    ui->devSector  ->setText(QString::number(d->sector));
    ui->devHcdi    ->setText(QString::number(d->hcdi));
    ui->devSwitch  ->setText(QString::number(d->switchId));
    ui->devLine    ->setText(QString::number(d->line));
    ui->devLineId  ->setText(QString::number(d->lineId));

    ui->dnaM_1 ->setText(QString::number(d->m01));
    ui->dnaM_2 ->setText(QString::number(d->m02));
    ui->dnaM_3 ->setText(QString::number(d->m03));
    ui->dnaM_4 ->setText(QString::number(d->m04));
    ui->dnaM_5 ->setText(QString::number(d->m05));
    ui->dnaM_6 ->setText(QString::number(d->m06));
    ui->dnaM_7 ->setText(QString::number(d->m07));
    ui->dnaM_8 ->setText(QString::number(d->m08));
    ui->dnaM_9 ->setText(QString::number(d->m09));
    ui->dnaM_10->setText(QString::number(d->m10));
    ui->dnaM_11->setText(QString::number(d->m11));
    ui->dnaM_12->setText(QString::number(d->m12));
    ui->dnaM_13->setText(QString::number(d->m13));
    ui->dnaM_14->setText(QString::number(d->m14));
    ui->dnaM_21->setText(QString::number(d->m21));
    ui->dnaM_22->setText(QString::number(d->m22));
    ui->dnaM_23->setText(QString::number(d->m23));
    ui->dnaM_24->setText(QString::number(d->m24));
    ui->dnaM_25->setText(QString::number(d->m25));
    ui->dnaM_26->setText(QString::number(d->m26));

    ui->dnaLongitude->setText(QString::number(d->longitude));
    ui->dnaLatitude ->setText(QString::number(d->latitude));
    ui->dnaAltitude ->setText(QString::number(d->altitude));

    ui->dnaTypePr    ->setText(QString::number(d->typePr));
    ui->dnaTypeSc    ->setText(QString::number(d->typeSc));
    ui->dnaWeight    ->setText(QString::number(d->weight));
    ui->dnaTemprature->setText(QString::number(d->temprature));
    ui->dnaPitchPr   ->setText(QString::number(d->pitchPr));
    ui->dnaPitchSc   ->setText(QString::number(d->pitchSc));
    ui->dnaRationPr  ->setText(QString::number(d->rationPr));
    ui->dnaRationSc  ->setText(QString::number(d->rationSc));
    ui->dnaPulsesPr  ->setText(QString::number(d->pulsesPr));
    ui->dnaPulsesSc  ->setText(QString::number(d->pulsesSc));
    ui->dnaTripPr    ->setText(QString::number(d->tripPr));
    ui->dnaTripSc    ->setText(QString::number(d->tripSc));
    ui->dnaCurvature ->setText(QString::number(d->curvature));

}

void MainWindow::modbusRegContral(quint16 regAddr, quint16 data, ModbusRegCmd_e type)
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, regAddr, 1);
    tBuf.setValue(0, data);
    emit modbusSetRegs(type, tBuf);
}

void MainWindow::modbusRegContral(quint16 regAddr, float data, ModbusRegCmd_e type)
{
    uint u = *(uint*)&data;
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, regAddr, 2);
    tBuf.setValue(0, (quint16)(u >> 16));
    tBuf.setValue(1, (quint16)u);
    qDebug() << data << tBuf.values();
    emit modbusSetRegs(type, tBuf);
}

void MainWindow::modbusRegContral(quint16 regAddr, int data, ModbusRegCmd_e type)
{
    quint16 fBuf[2] = {0};
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, regAddr, 2);

    memcpy(fBuf, &data, sizeof(int));
    tBuf.setValue(0, fBuf[0]);
    tBuf.setValue(1, fBuf[1]);

    emit modbusSetRegs(type, tBuf);
}

QModbusDataUnit MainWindow::modbusMotorContralDefault(int startRegAddr)
{
    QModbusDataUnit tBuf;
    float speed, trip;
    int power = 0, pos = 0;
    uint u;

    if (startRegAddr == 0x40)
    {
        speed = ui->motorSetPosSpeed1->text().toFloat();
        trip  = ui->motorSetPosTrip1->text().toFloat();
        power = ui->motorSetPower1->text().toInt();
        pos   = ui->motorSetPos1->text().toInt();
        QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, startRegAddr, 16);
        tBuf.setValue(0, 1);
        u = *(uint*)&speed;
        tBuf.setValue(7, u >> 8);
        tBuf.setValue(8, (quint16)u);
        u = *(uint*)&trip;
        tBuf.setValue(9, u >> 8);
        tBuf.setValue(10, (quint16)u);
        tBuf.setValue(12, power >> 8);
        tBuf.setValue(13, (quint16)power);
        tBuf.setValue(14, pos >> 8);
        tBuf.setValue(15, (quint16)pos);
        return tBuf;
    }
    else if (startRegAddr == 0x80)
    {
        speed = ui->motorSetPosSpeed2->text().toFloat();
        trip  = ui->motorSetPosTrip2->text().toFloat();
        power = ui->motorSetPower2->text().toInt();
        pos   = ui->motorSetPos2->text().toInt();
        QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, startRegAddr, 16);
        tBuf.setValue(0, 1);
        u = *(uint*)&speed;
        tBuf.setValue(7, u >> 8);
        tBuf.setValue(8, (quint16)u);
        u = *(uint*)&trip;
        tBuf.setValue(9, u >> 8);
        tBuf.setValue(10, (quint16)u);
        tBuf.setValue(12, power >> 8);
        tBuf.setValue(13, (quint16)power);
        tBuf.setValue(14, pos >> 8);
        tBuf.setValue(15, (quint16)pos);
        return tBuf;
    }

    QModbusDataUnit none;
    return none;
}

void MainWindow::uint16ToDoubleByte(float &src, quint16 *u)
{
    uint dataUint = (u[0] << 16) + u[1];
    memcpy(&src, &dataUint, sizeof(float));
}

void MainWindow::uint16ToDoubleByte(int &src, quint16 *u)
{
    uint dataUint = (u[0] << 16) + u[1];
    memcpy(&src, &dataUint, sizeof(float));
}

void MainWindow::unpackVersion(QVector<quint16> data, char * version)
{
    int v1, v2, v3, v4;
    char verType[32] = {0};

    v1 = data[0] >> 8;
    v2 = (quint8)data[0];
    v3 = (quint8)data[1];
    v4 = data[1] >> 12;

    switch (v4) {
    case 0: break;
    case 1:
        if (v3 == 0)
        {
            sprintf(verType, "release");
        }
        else
        {
            sprintf(verType, "rev");
        }
        break;
    case 2:
        sprintf(verType, "alpha");
        break;
    case 4:
        sprintf(verType, "beta");
        break;
    case 6:
        sprintf(verType, "rc");
        break;
    case 8:
        sprintf(verType, "delta");
        break;
    default:
        sprintf(verType, "Unknow");
        break;
    }

    sprintf(version, "%u-%u-%u-%s%u", v1, v2, v3, verType, data[1] >> 8 & 0x0f);
}


void MainWindow::on_setMaddrBtn_clicked()
{
    bool ok = false;
    quint8 maddr = ui->maddr->text().toUInt(&ok, 16);

    if (!ok) {
        QMessageBox::warning(this, "错误", "Modbus通讯地址错误，请检查后重试");
        return;
    }

    m_modbus->setMaddr(maddr);
}

void MainWindow::on_getSysTimeBtn_clicked()
{
    m_modbus->modbusGetRegs(MODBUS_REG_GET_SYSTEM_TIME, 0x05, 6);
}

void MainWindow::on_setSysTimeBtn_clicked()
{
    UiSetTime * timeDialog = new UiSetTime(this);
    connect(timeDialog, &UiSetTime::setTime, this, [=](QString time){
        sprintf(m_info->system.timestamp, "%s", time.toUtf8().data());

        quint16 data[6] = {0};
        sscanf(m_info->system.timestamp, "%hu-%hu-%hu %hu:%hu:%hu", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);

        QModbusDataUnit writeData(QModbusDataUnit::HoldingRegisters, 0x05, 6); // 从地址0x0开始写6个寄存器
        for(int i = 0; i < 6; i++)
            writeData.setValue(i, data[i]);

        qDebug() << "设置系统时间：" << writeData.values();
        emit modbusSetRegs(MODBUS_REG_SET_SYSTEM_TIME, writeData);


        timeDialog->close();
        timeDialog->deleteLater();
    });
    timeDialog->exec();
}

/**
 * @brief MainWindow::on_rebootBtn_clicked 重启设备
 */
void MainWindow::on_rebootBtn_clicked()
{
    modbusRegContral(0x03, (quint16)1, MODBUS_REG_SET_DEV_RESET);
}

/**
 * @brief MainWindow::on_resetBtn_clicked 重置设备
 */
void MainWindow::on_resetBtn_clicked()
{
    modbusRegContral(0x04, (quint16)1, MODBUS_REG_SET_DEV_RESET);
}

/**
 * @brief MainWindow::on_localSetMaddrBtn_clicked 设置modbus地址
 */
void MainWindow::on_localSetMaddrBtn_clicked()
{
    modbusRegContral(0x00, (quint16)ui->devMaddr->text().toUInt(nullptr, 16), MODBUS_REG_SET_MADDR);
}

/**
 * @brief MainWindow::on_localSetBaudrateBtn_clicked 设置波特率
 */
void MainWindow::on_localSetBaudrateBtn_clicked()
{
    modbusRegContral(0x01, (quint16)ui->devBaudrate->currentIndex(), MODBUS_REG_SET_BAUDRATE);
}

/**
 * @brief MainWindow::on_localSetLogLevelBtn_clicked 设置调试等级
 */
void MainWindow::on_localSetLogLevelBtn_clicked()
{
    modbusRegContral(0x02, (quint16)ui->devLogLevel->currentIndex(), MODBUS_REG_SET_LOG_LEVEL);
}

// 算法控制 主轴
void MainWindow::on_btnMotorAlgo1_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 16); // 算法控制
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 算法控制 副轴
void MainWindow::on_btnMotorAlgo2_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 16); // 算法控制
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 紧急停止 主轴
void MainWindow::on_btnMotorStop1_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(2, 1); // 急停
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 紧急停止 副轴
void MainWindow::on_btnMotorStop2_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(2, 1); // 急停
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 复位驱动器故障 主轴
void MainWindow::on_btnMotorReset1_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(3, 1); // 复位
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 复位驱动器故障 副轴
void MainWindow::on_btnMotorReset2_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(3, 1); // 复位
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 零点校正 主轴
void MainWindow::on_btnMotorZero1_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(6, 1); // 零点校正
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 零点校正 副轴
void MainWindow::on_btnMotorZero2_clicked()
{
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(6, 1); // 零点校正
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 位置运行 主轴
void MainWindow::on_btnMotorPos1_clicked()
{
    float speed = ui->motorSetPosSpeed1->text().toFloat();
    float trip  = ui->motorSetPosTrip1 ->text().toFloat();
    uint uSpeed = *(uint*)&speed;
    uint uTrip  = *(uint*)&trip;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(1, 1); // 位置运行
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);
    tBuf.setValue(9,  (quint16)(uTrip  >> 16)); // 行程给定
    tBuf.setValue(10, (quint16) uTrip);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 位置运行 副轴
void MainWindow::on_btnMotorPos2_clicked()
{
    float speed = ui->motorSetPosSpeed2->text().toFloat();
    float trip  = ui->motorSetPosTrip2 ->text().toFloat();
    uint uSpeed = *(uint*)&speed;
    uint uTrip  = *(uint*)&trip;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(1, 1); // 位置运行
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);
    tBuf.setValue(9,  (quint16)(uTrip  >> 16)); // 行程给定
    tBuf.setValue(10, (quint16) uTrip);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 正向点动 主轴
void MainWindow::on_btnMotorForward1_clicked()
{
    float speed = ui->motorSetJogSpeed1->text().toFloat();
    uint uSpeed = *(uint*)&speed;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(4, 1); // 正向点动
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 反向点动 主轴
void MainWindow::on_btnMotorReverse1_clicked()
{
    float speed = ui->motorSetJogSpeed1->text().toFloat();
    uint uSpeed = *(uint*)&speed;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(5, 1); // 反向点动
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 正向点动 副轴
void MainWindow::on_btnMotorForward2_clicked()
{
    float speed = ui->motorSetJogSpeed2->text().toFloat();
    uint uSpeed = *(uint*)&speed;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(4, 1); // 正向点动
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 反向点动 副轴
void MainWindow::on_btnMotorReverse2_clicked()
{
    float speed = ui->motorSetJogSpeed2->text().toFloat();
    uint uSpeed = *(uint*)&speed;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0, 1); // 手动控制
    tBuf.setValue(5, 1); // 反向点动
    tBuf.setValue(7,  (quint16)(uSpeed >> 16)); // 速度给定
    tBuf.setValue(8,  (quint16) uSpeed);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 重置当前位置 主轴
void MainWindow::on_btnMotorResetPos1_clicked()
{
    int pos = ui->motorSetPos1->text().toInt();
    uint uPos = *(uint*)&pos;
    QModbusDataUnit posBuf(QModbusDataUnit::HoldingRegisters, 0x4e, 2);
    posBuf.setValue(0,  (quint16)(uPos >> 16)); // 重置位置值
    posBuf.setValue(0,  (quint16) uPos);
    emit modbusSetRegs(MODBUS_REG_NO_FEEDBACK, posBuf);

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x40, 12);
    tBuf.setValue(0,  1); // 手动控制
    tBuf.setValue(11, 1); // 重置当前位置
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 重置当前位置 副轴
void MainWindow::on_btnMotorResetPos2_clicked()
{
    int pos = ui->motorSetPos2->text().toInt();
    uint uPos = *(uint*)&pos;
    QModbusDataUnit posBuf(QModbusDataUnit::HoldingRegisters, 0x8e, 2);
    posBuf.setValue(0,  (quint16)(uPos >> 16)); // 重置位置值
    posBuf.setValue(0,  (quint16) uPos);
    emit modbusSetRegs(MODBUS_REG_NO_FEEDBACK, posBuf);

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x80, 12);
    tBuf.setValue(0,  1); // 手动控制
    tBuf.setValue(11, 1); // 重置当前位置
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 功率上限 主轴
void MainWindow::on_btnMotorPowerMax1_clicked()
{
    int power = ui->motorSetPower1->text().toInt();
    uint uPower = *(uint*)&power;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x4c, 2);
    tBuf.setValue(0,  (quint16)(uPower >> 16)); // 功率上限
    tBuf.setValue(1,  (quint16) uPower);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

// 功率上限 副轴
void MainWindow::on_btnMotorPowerMax2_clicked()
{
    int power = ui->motorSetPower2->text().toInt();
    uint uPower = *(uint*)&power;

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x8c, 2);
    tBuf.setValue(0,  (quint16)(uPower >> 16)); // 功率上限
    tBuf.setValue(1,  (quint16) uPower);

    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

void MainWindow::on_localSetClusterSwitchBtn_clicked()
{
    ui->l_clusterDbg->setText(ui->devClusterDbg->isChecked() ? "打开" : "关闭");
    modbusRegContral(0xc0, (quint16)ui->devClusterDbg->isChecked());
}

void MainWindow::on_localSetMotorSwitchBtn_clicked()
{
    ui->l_motorDbg->setText(ui->devMotorDbg->isChecked() ? "打开" : "关闭");
    modbusRegContral(0xc1, (quint16)ui->devMotorDbg->isChecked());
}

void MainWindow::on_btnMotorSetLog1_clicked()
{
    modbusRegContral(0xc2, (quint16)ui->motorSetLog1->currentIndex());
}

void MainWindow::on_btnMotorSetLog2_clicked()
{
    modbusRegContral(0xc3, (quint16)ui->motorSetLog2->currentIndex());
}

void MainWindow::on_locErrCodeResetBtn_clicked()
{
    modbusRegContral(0xd2);
}

void MainWindow::on_locEmergencyResetBtn_clicked()
{
    modbusRegContral(0xd3);
}

void MainWindow::on_locEmerStopBtn_clicked()
{
    modbusRegContral(0xd4, (quint16)ui->locEmerStopBtn->isChecked());
}
// 允许回平和避光位自动切换
void MainWindow::on_auto_switch_enable_clicked()
{
    modbusRegContral(0xd1, (quint16)ui->auto_switch_enable->isChecked());
}
// 工程师权限
void MainWindow::on_engineer_authority_clicked()
{
    modbusRegContral(0xd5, (quint16)ui->engineer_authority->isChecked());
}
// 模拟反射进安全区
void MainWindow::on_simulate_reflected_to_safety_zone_clicked()
{
    modbusRegContral(0xd6, (quint16)ui->simulate_reflected_to_safety_zone->isChecked());
}
// 处于校正队列
void MainWindow::on_in_calibration_queue_clicked()
{
    modbusRegContral(0xd7, (quint16)ui->in_calibration_queue->isChecked());
}
// 屏蔽备用点坐标限位
void MainWindow::on_disable_backup_point_corrdinate_limit_clicked()
{
    modbusRegContral(0xd8, (quint16)ui->disable_backup_point_corrdinate_limit->isChecked());
}
// 模拟完成零点校正
void MainWindow::on_simulate_zero_point_correction_ready_clicked()
{
    modbusRegContral(0xd9, (quint16)ui->simulate_zero_point_correction_ready->isChecked());
}
// 模拟完成上下限位检查
void MainWindow::on_simulate_check_limit_pos_ready_clicked()
{
    modbusRegContral(0xda, (quint16)ui->simulate_check_limit_pos_ready->isChecked());
}
// 模拟回平已完成
void MainWindow::on_simulate_back_horizontal_ready_clicked()
{
    modbusRegContral(0xdb, (quint16)ui->simulate_back_horizontal_ready->isChecked());
}
// 模拟紧急安置
void MainWindow::on_simulate_emergency_placement_clicked()
{
    modbusRegContral(0xdc, (quint16)ui->simulate_emergency_placement->isChecked());
}
// 码值倍率设置
void MainWindow::on_code_multiplier_val_enable_clicked()
{
    bool ok = false;
    float codeVal = ui->code_multiplier_val->text().toFloat(&ok);
    if (!ok) {
        QMessageBox::information(this, "设置错误", "输入的码值倍率值有误！");
        return;
    }
    modbusRegContral(0xde, codeVal);
    modbusRegContral(0xdd, (quint16)ui->code_multiplier_val_enable->isChecked());
}
// 启用入射光线死区
void MainWindow::on_enable_incident_light_dead_zone_clicked()
{
    modbusRegContral(0xe0, (quint16)ui->enable_incident_light_dead_zone->isChecked());
}
// 屏蔽备用点距离要求
void MainWindow::on_disable_backup_point_distance_requirements_clicked()
{
    modbusRegContral(0xe1, (quint16)ui->disable_backup_point_distance_requirements->isChecked());
}
// 启用行程提前
void MainWindow::on_enable_advance_travel_clicked()
{
    modbusRegContral(0xe2, (quint16)ui->enable_advance_travel->isChecked());
}
// 角度行程提前1min
void MainWindow::on_angle_travel_advance_1min_clicked()
{
    modbusRegContral(0xe3, (quint16)ui->angle_travel_advance_1min->isChecked());
}
// 启用重力补偿
void MainWindow::on_enable_gravity_compensation_clicked()
{
    modbusRegContral(0xe4, (quint16)ui->enable_gravity_compensation->isChecked());
}
// 启用纠偏补偿
void MainWindow::on_enable_correction_compensation_clicked()
{
    modbusRegContral(0xe5, (quint16)ui->enable_correction_compensation->isChecked());
}
// 启用功率管理
void MainWindow::on_locPowerLimitSetBtn_clicked()
{
    bool ok1 = false, ok2 = false;
    int power1 = 0, power2 = 0;
    power1 = ui->maxPowerMain->text().toInt(&ok1);
    power2 = ui->maxPowerSub->text().toInt(&ok2);
    if (!ok1 || !ok2) {
        QMessageBox::information(this, "设置错误", "输入的功率上线值有误！");
        return;
    }
    modbusRegContral(0xe7, (quint16)power1, MODBUS_REG_NO_FEEDBACK);
    modbusRegContral(0xe8, (quint16)power2, MODBUS_REG_NO_FEEDBACK);
    modbusRegContral(0xe6, (quint16)ui->enablePowerManger->isChecked());
}

void MainWindow::on_btnStop_clicked()
{
    if (m_info->app.stop == 0) {
        ui->btnStop->setIcon(QIcon(":/res/reload-restore-icon-27.png"));
        modbusRegContral(0xc4, (quint16)1, MODBUS_REG_NO_FEEDBACK);
        m_info->app.stop = 1;
    } else {
        ui->btnStop->setIcon(QIcon(":/res/stop.png"));
        modbusRegContral(0xc4, (quint16)0, MODBUS_REG_NO_FEEDBACK);
        m_info->app.stop = 0;
    }
}

void MainWindow::on_btnSetCmd_clicked()
{
    quint16 cmd = ui->cmdCmd->currentIndex();
    float x = ui->cmdX->text().toFloat();
    float y = ui->cmdY->text().toFloat();
    float z = ui->cmdZ->text().toFloat();

    uint uX, uY, uZ;
    memcpy(&uX, &x, sizeof(x));
    memcpy(&uY, &y, sizeof(x));
    memcpy(&uZ, &z, sizeof(x));

    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, g_regMap[MODBUS_REG_GET_CMD].regAddr, 7);
    tBuf.setValue(0, cmd);
    tBuf.setValue(1, uX >> 16);
    tBuf.setValue(2, uX);
    tBuf.setValue(3, uY >> 16);
    tBuf.setValue(4, uY);
    tBuf.setValue(5, uZ >> 16);
    tBuf.setValue(6, uZ);

    qDebug() << "设置CMD：" << tBuf.values();
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf);
}

/**
 * @brief MainWindow::on_btnSetDna_clicked DNA信息设置
 */
void MainWindow::on_btnSetDna_clicked()
{
    int idx = 0;

    float m[29] = {0};
    uint um[29] = {0};
    m[0]  = ui->dnaM_1 ->text().toFloat();
    m[1]  = ui->dnaM_2 ->text().toFloat();
    m[2]  = ui->dnaM_3 ->text().toFloat();
    m[3]  = ui->dnaM_4 ->text().toFloat();
    m[4]  = ui->dnaM_5 ->text().toFloat();
    m[5]  = ui->dnaM_6 ->text().toFloat();
    m[6]  = ui->dnaM_7 ->text().toFloat();
    m[7]  = ui->dnaM_8 ->text().toFloat();
    m[8]  = ui->dnaM_9 ->text().toFloat();
    m[9]  = ui->dnaM_10->text().toFloat();
    m[10] = ui->dnaM_11->text().toFloat();
    m[11] = ui->dnaM_12->text().toFloat();
    m[12] = ui->dnaM_13->text().toFloat();
    m[13] = ui->dnaM_14->text().toFloat();
    m[14] = ui->dnaM_21->text().toFloat();
    m[15] = ui->dnaM_22->text().toFloat();
    m[16] = ui->dnaM_23->text().toFloat();
    m[17] = ui->dnaM_24->text().toFloat();
    m[18] = ui->dnaM_25->text().toFloat();
    m[19] = ui->dnaM_26->text().toFloat();

    m[20] = ui->dnaLongitude->text().toFloat();
    m[21] = ui->dnaLatitude ->text().toFloat();
    m[22] = ui->dnaAltitude ->text().toFloat();

    m[23] = ui->dnaWeight    ->text().toFloat();
    m[24] = ui->dnaTemprature->text().toFloat();
    m[25] = ui->dnaPitchPr   ->text().toFloat();
    m[26] = ui->dnaPitchSc   ->text().toFloat();
    m[27] = ui->dnaRationPr  ->text().toFloat();
    m[28] = ui->dnaRationSc  ->text().toFloat();

    QModbusDataUnit tBuf1(QModbusDataUnit::HoldingRegisters, 0x0276, 48);
    for (int i = 0; i < 23; i++)
    {
        memcpy(&um[i], &m[i], sizeof(uint));
        tBuf1.setValue(idx++, um[i] >> 16);
        tBuf1.setValue(idx++, um[i]);
    }


    tBuf1.setValue(idx++, ui->dnaTypePr->text().toUInt());
    tBuf1.setValue(idx++, ui->dnaTypeSc->text().toUInt());

    qDebug() << "镜场位置参数设置1: " << tBuf1.values();
    emit modbusSetRegs(MODBUS_REG_NO_FEEDBACK, tBuf1);

    idx = 0;
    QModbusDataUnit tBuf2(QModbusDataUnit::HoldingRegisters, 0x02a6, 20);
    for (int i = 23; i < 29; i++)
    {
        memcpy(&um[i], &m[i], sizeof(uint));
        tBuf2.setValue(idx++, um[i] >> 16);
        tBuf2.setValue(idx++, um[i]);
    }
    tBuf2.setValue(idx++, ui->dnaPulsesPr->text().toUInt());
    tBuf2.setValue(idx++, ui->dnaPulsesSc->text().toUInt());

    tBuf2.setValue(idx++, ui->dnaTripPr->text().toUInt() >> 16);
    tBuf2.setValue(idx++, (quint16)ui->dnaTripPr->text().toUInt());
    tBuf2.setValue(idx++, ui->dnaTripSc->text().toUInt() >> 16);
    tBuf2.setValue(idx++, (quint16)ui->dnaTripSc->text().toUInt());

    float curvature = ui->dnaCurvature->text().toFloat();
    uint u = *(uint *)&curvature;
    tBuf2.setValue(idx++, u >> 16);
    tBuf2.setValue(idx++, (quint16)u);

    qDebug() << "镜场位置参数设置2: " << tBuf2.values();
    emit modbusSetRegs(MODBUS_REG_FEEDBACK, tBuf2);
}


/**
 * @brief MainWindow::on_localSetPosBtn_clicked 镜场位置参数设置
 */
void MainWindow::on_localSetPosBtn_clicked()
{
    int idx = 0;
    QModbusDataUnit tBuf(QModbusDataUnit::HoldingRegisters, 0x026e, 8);
    tBuf.setValue(idx++, ui->devFieleId->text().toUInt());
    tBuf.setValue(idx++, ui->devRow    ->text().toUInt());
    tBuf.setValue(idx++, ui->devCol    ->text().toUInt());
    tBuf.setValue(idx++, ui->devSector ->text().toUInt());
    tBuf.setValue(idx++, ui->devHcdi   ->text().toUInt());
    tBuf.setValue(idx++, ui->devSwitch ->text().toUInt());
    tBuf.setValue(idx++, ui->devLine   ->text().toUInt());
    tBuf.setValue(idx++, ui->devLineId ->text().toUInt());

    qDebug() << "镜场位置参数设置: " << tBuf.values();
    emit modbusSetRegs(MODBUS_REG_NO_FEEDBACK, tBuf);
    QTimer::singleShot(100, this, [=](){
        modbusRegContral(0x200);
    });
}

void MainWindow::on_localDnaSaveBtn_clicked()
{
    modbusRegContral(0x200);
}
